package com.qiyun.asyncarrange;

import java.util.concurrent.*;

//200
public class CompletableFutureTest05 {
    public static ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
            200,
            10,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(100000),
            Executors.defaultThreadFactory(),//默认线程工厂
            new ThreadPoolExecutor.AbortPolicy()//拒绝策略
            //如果不想抛弃还要执行。可以使用new ThreadPoolExecutor.CallerRunsPolicy()
    );


    /**
     * 线程串行化
     *
     * @param args
     */
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        /**
         *     public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn)
         *     public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn)
         *     public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn, Executor executor)
         *
         *     public <U> CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action)
         *     public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action)
         *     public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action, Executor executor)
         *
         *     public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,Runnable action)
         *     public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action)
         *     public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor)
         *
         * 两个任务必须都完成，触发该任务。
         *
         * runAfterBoth：组合两个 future，不需要获取 future 的结果，只需两个 future 处理完任务后，处理该任务。
         * thenAcceptBoth：组合两个 future，获取两个 future 任务的返回结果，然后处理任务，没有返回值。
         * thenCombine：组合两个 future，获取两个 future 的返回结果，并返回当前任务的返回值
         *
         */

        /*
          1. 两个都完成
         */
        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程" + Thread.currentThread().getId() + ",执行。。。");
            int i = 10 / 3;
            System.out.println("任务1线程运行结果..." + i);
            return i;
        }, executor);
        CompletableFuture<Integer> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程" + Thread.currentThread().getId() + ",执行。。。");
            int i = 10 / 2;
            System.out.println("任务2线程运行结果..." + i);
            return i;
        }, executor);

        /*
        runAfterBoth：组合两个future，不需要获取future的结果，只需两个future处理完任务后，处理该任务。
         */
      /* future01.runAfterBothAsync(future02,()->{
            //任务3肯定是 任务1,2都结束之后才会执行
            System.out.println("任务3线程" + Thread.currentThread().getId() + ",执行。。。");
        },executor);*/




        /*
        thenAcceptBoth：组合两个future，获取两个future任务的返回结果，然后处理任务，没有返回值。
         */
        /*future01.thenAcceptBothAsync(future02, (f1, f2) -> {
            //任务3肯定是 任务1,2都结束之后才会执行
            System.out.println("任务3线程" + Thread.currentThread().getId()
                        + "开始执行之前的结果" + f1 + "-*-*-*-" + f2);
        }, executor);*/




        /*
        thenCombine：组合两个future，获取两个future的返回结果，并返回当前任务的返回值
         */
        CompletableFuture<String> future03 = future01.thenCombineAsync(future02, (f1, f2) -> {
            //任务3肯定是 任务1,2都结束之后才会执行
            //System.out.println("任务3线程" + Thread.currentThread().getId() + "开始执行之前的结果" + f1 + "-*-*-*-" + f2);
            return f1 + f2+"";
        }, executor);

        System.out.println("main...end...合并后的结果"+future03.get());



    }

}
